unit savedisassemblyfrm;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs,symbolhandler,disassembler, StdCtrls, ComCtrls, ActnList;

type TSaveDisassemblyThread=class(TThread)
  public
    progressbar: tprogressbar;
    start: dword;
    stop: dword;
    address: boolean;
    bytes: boolean;
    opcode: boolean;
    filename: string;
    procedure execute; override;
end;


type
  TfrmSavedisassembly = class(TForm)
    Button1: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
    Label1: TLabel;
    Label2: TLabel;
    CheckBox1: TCheckBox;
    CheckBox2: TCheckBox;
    CheckBox3: TCheckBox;
    SaveDialog1: TSaveDialog;
    ProgressBar1: TProgressBar;
    procedure Button1Click(Sender: TObject);
    procedure FormClose(Sender: TObject; var Action: TCloseAction);
    procedure actCancelExecute(Sender: TObject);
  private
    { Private declarations }
    SaveDisassemblyThread: TSaveDisassemblyThread;
  public
    { Public declarations }
  end;

var
  frmSavedisassembly: TfrmSavedisassembly;

implementation

{$R *.dfm}

procedure TSaveDisassemblyThread.execute;
var currentaddress: dword;
    f: textfile;
    temps: string;
    temps2: string;
    addresspart, bytepart, opcodepart: string;
    i: integer;
begin
  currentaddress:=start;

  assignfile(f,filename);
  rewrite(f);

  i:=0;

  while (not terminated) and (currentaddress<stop) do
  begin
    temps:=disassemble(currentaddress); //contains the addresspart, bytepart and opcode part
    temps2:=copy(temps,pos('-',temps)+2,length(temps)); //contains the bytepart and opcode part
    opcodepart:=copy(temps2,pos('-',temps2)+2,length(temps2));

    addresspart:=copy(temps,1,pos('-',temps)-2);
    bytepart:=copy(temps2,1,pos('-',temps2)-2);

    temps:='';
    if address then
    begin
      temps:=addresspart;
      if bytes or opcode then temps:=temps+' - ';
    end;

    if bytes then
    begin
      temps:=temps+bytepart;
      if opcode then
      begin
        temps:=temps+' ';
        if address then
          while length(temps)<(11+(9*3)) do temps:=temps+' '
        else
          while length(temps)<(9*3) do temps:=temps+' ';

        temps:=temps+'- '
      end;
    end;

    if opcode then temps:=temps+opcodepart;

    writeln(f,temps);
    if (i mod 10=0) and (currentaddress<$80000006) then
      progressbar.position:=currentaddress;
  end;

  flush(f);
  closefile(f);

  if not terminated then postmessage(frmSavedisassembly.Handle,wm_close,0,0);
end;

procedure TfrmSavedisassembly.Button1Click(Sender: TObject);
var start,stop: dword;
begin
  if SaveDisassemblyThread<>nil then
  begin
    SaveDisassemblyThread.Terminate;
    SaveDisassemblyThread.WaitFor;
    freeandnil(SaveDisassemblyThread);
    button1.Caption:='Save';
    exit;
  end;

  start:=strtoint('$'+edit1.Text);
  stop:=strtoint('$'+edit2.text);
  if savedialog1.Execute then
  begin
    SaveDisassemblyThread:=TSaveDisassemblyThread.Create(true);
    SaveDisassemblyThread.address:=checkbox1.checked;
    SaveDisassemblyThread.bytes:=checkbox2.Checked;
    SaveDisassemblyThread.opcode:=checkbox3.Checked;
    SaveDisassemblyThread.start:=start;
    SaveDisassemblyThread.stop:=stop;
    SaveDisassemblyThread.filename:=savedialog1.FileName;

    if (start<$80000006) and (stop<$80000006) then
    begin
      progressbar1.Max:=stop;
      progressbar1.Min:=start;
      progressbar1.Position:=start;
      if not progressbar1.Visible then progressbar1.Visible:=true;
    end
    else
      progressbar1.Visible:=false;

    SaveDisassemblyThread.progressbar:=progressbar1;

    button1.caption:='Stop saving';
    SaveDisassemblyThread.resume;
  end;
end;

procedure TfrmSavedisassembly.FormClose(Sender: TObject;
  var Action: TCloseAction);
begin
  if SaveDisassemblyThread<>nil then
  begin
    SaveDisassemblyThread.Terminate;
    SaveDisassemblyThread.WaitFor;
    freeandnil(SaveDisassemblyThread);
  end;

  action:=cafree;
  frmSavedisassembly:=nil
end;

procedure TfrmSavedisassembly.actCancelExecute(Sender: TObject);
begin
  close;
end;

end.
